Skip to content

Excel 欄位寬度的隱藏陷阱

TLDR

  • Excel 的欄位寬度計算並非絕對數值,而是取決於該檔案的「預設字型」與「字型大小」。
  • 針對個別儲存格設定字型不會影響欄寬,必須調整工作簿(Workbook)層級的預設字型設定。
  • 使用 NPOI 或 EPPlus 匯出 Excel 時,若未統一預設字型,將導致欄位寬度與預期不符。
  • 變更 Excel 預設字型後,必須重啟 Excel 軟體並建立新檔案才能正確套用。
  • EPPlus 在處理預設字型套用上較為直觀,NPOI 則需注意其對預設字型屬性的支援限制。

Excel 預設字型對欄寬的影響

什麼情況下會遇到這個問題:當開發者使用 NPOI 或 EPPlus 匯出 Excel,發現設定了相同的欄寬數值,但產出的 Excel 欄位寬度卻與客戶提供的範本不一致時。

Excel 的欄寬計算邏輯是以「預設字型」的字元寬度為基準進行換算。即使開發者針對特定儲存格設定了字型,該設定也不會改變整欄的計算基準。若匯出檔案的預設字型與客戶範本不同(例如預設為 Calibri 11 點,而範本為其他設定),即便欄寬數值相同,實際顯示的寬度也會產生落差。

WARNING

變更預設字體大小後,必須關閉所有 Excel 文件,並建立新的 Excel 文件,才能套用新的設定。

使用 NPOI 設定預設字型

什麼情況下會遇到這個問題:在使用 NPOI 進行 Excel 報表開發,且需要精確控制欄位顯示寬度時。

在 NPOI 中,雖然可以透過 GetFontAt(0) 存取預設字型並修改屬性,但實測發現,修改後的字型名稱與大小可能無法完全正確地反映在欄寬計算基準上,導致產出的 Excel 欄寬與預期不符。

csharp
using IWorkbook workbook = new XSSFWorkbook();
IFont defaultFont = workbook.GetFontAt(0);
// 修改預設字型屬性
defaultFont.FontName = "微軟正黑體";
defaultFont.FontHeightInPoints = 20;

workbook.CreateSheet()
    .CreateRow(0)
    .CreateCell(0)
    .SetCellValue("Test");

using FileStream fileStream = new("Test.xlsx", FileMode.Create, FileAccess.Write);
workbook.Write(fileStream);

使用 EPPlus 設定預設字型

什麼情況下會遇到這個問題:當專案選用 EPPlus 作為 Excel 處理工具,並希望透過程式碼確保匯出檔案的預設樣式與客戶需求一致時。

EPPlus 允許直接存取 Workbook.Styles.Fonts 來修改預設樣式。相較於 NPOI,EPPlus 在修改預設字型後,能更有效地將該設定套用於欄寬計算基準,確保欄寬顯示的一致性。

csharp
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using ExcelPackage package = new();
// 存取並修改預設字型
ExcelFontXml defaultFont = package.Workbook.Styles.Fonts[0];
defaultFont.Name = "微軟正黑體";
defaultFont.Size = 20;

ExcelWorksheet sheet = package.Workbook.Worksheets.Add("Sheet1");
sheet.Cells[1,1,1,1].Value = "Test";

using FileStream fileStream = new("Test.xlsx", FileMode.Create, FileAccess.Write);
package.SaveAs(fileStream);

結論

  • 欄寬不一致的主因在於「預設字型」設定不同,而非單純的欄寬數值問題。
  • 若需與特定範本對齊,應優先檢查並統一程式產出檔案的預設字型設定。
  • 建議在專案初期即定義好統一的 Excel 樣式配置,避免在個別儲存格重複調整樣式卻忽略了全域的預設基準。

異動歷程

    • 初版文件建立。